/*
 * @Author: your name
 * @Date: 2022-04-25 08:38:11
 * @LastEditTime: 2022-09-08 14:52:22
 * @LastEditors: 飞越疯人院 353362604@qq.com
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \reconfiguration-administration\src\Common\Forge\Modal.jsx
 */
import { Http } from '../Api'
import { useState, useEffect, useRef } from 'react'
import { message, Modal, Tabs, Form, Input, InputNumber, Select, Button } from 'antd'
import { useBoolean, useEventEmitter, useSetState, useLocalStorageState, useRequest } from 'ahooks'
import { APSModal } from './APSModal'

const { TextArea } = Input
const { Option } = Select
const { Autodesk, THREE } = window
const config3d = { extensions: ['ToolbarExtension'] }

// 灯光属性 组件固定数据
const LightPreset = {
    0: '简单灰色',
    1: '清晰亮点',
    2: '黑暗天空',
    3: '灰色客房',
    4: '照相亭',
    5: '宁静',
    6: '无边泳池',
    7: '简单白',
    8: '河岸',
    9: '对比度',
    10: '轮辋亮点',
    11: '冷光',
    12: '暖光',
    13: '柔和光',
    14: '栅格灯',
    15: '广场',
    16: '雪原',
}

// forge内容
export const ForgeModel = ({ scene, initializationEvent }) => {
    const forgeModel = useRef(null)

    const [ModelUrlList, setModelUrlList] = useState()
    const [Viewing, setViewing] = useState()
    const ModelEvent = useEventEmitter()
    const [ModelList, setModelList] = useState([])
    const [ModelSelect, setModelSelect] = useState({})
    const [IsStart, { setTrue }] = useBoolean(false)
    const [SceneDetailData, setSceneDetailData] = useState()
    const [configure, setConfigure] = useSetState({ longitude: '0', latitude: '0', altitude: '#000000' })
    // 获取场景明细
    const { runAsync: getScenesDetails } = useRequest(Http, { manual: true })
    // 获取模型列表
    const { runAsync: getBimFileOrganizationRelations } = useRequest(Http, { manual: true })
    ModelEvent.useSubscription(({ url, lng, lat, alt }) => {
        if (url) {
            if (IsStart) {
                Viewing.tearDown()
                setTimeout(() => {
                    Viewing.loadModel(ModelList.find(v => v.uuid === url).url, {}, () => {
                        Viewing.setLightPreset(Number(configure.longitude))
                        Viewing.setEnvMapBackground(Number(configure.latitude))
                        Viewing.setGroundShadowColor(new THREE.Color(configure.altitude))
                    })
                }, 1000)
            } else {
                Viewing.start(ModelList.find(v => v.uuid === url).url, {}, () => {
                    setTrue()
                    Viewing.setLightPreset(1)
                    Viewing.setEnvMapBackground(false)
                })
            }
        } else if (lng) {
            Viewing.setLightPreset(Number(lng))
            setConfigure({ longitude: lng })
        } else if (lat) {
            Viewing.setEnvMapBackground(Number(lat))
            setConfigure({ latitude: lat })
        } else if (alt) {
            Viewing.setGroundShadowColor(new THREE.Color(alt))
            setColor(alt)
        }
    })
    // 节流change数据
    const { run: setColor } = useRequest(async data => new Promise(resolve => resolve(data)), {
        throttleWait: 1000,
        manual: true,
        onSuccess: res => setConfigure({ altitude: res }),
    })

    useEffect(() => {
        const viewing = new Autodesk.Viewing.GuiViewer3D(forgeModel.current, config3d)
        Autodesk.Viewing.Initializer({ env: 'Local' }, () => {
            setViewing(viewing)
            message.info('初始化完成')
            getBimFileOrganizationRelations({ url: 'getBimFileOrganizationRelations' }).then(res => {
                setModelUrlList(res.list)
                const list = res.list.reduce((acc, item) => ({ ...acc, [item.uuid]: item.bim_FilesName }), {})
                console.log(list)
                setModelList([...list])

                // getScenesDetails({ url: `getScenesDetails`, data: { ScenesUuid: scene.uuid } }).then(
                //     ({ total, list }) => {
                //         if (total && total !== 0) {
                //             viewing.start(data.find(v => v.uuid === list[0].constitutesUuid).url, {}, () => {
                //                 setConfigure({
                //                     longitude: list[0].longitude,
                //                     latitude: list[0].latitude,
                //                     altitude: list[0].altitude,
                //                 })

                //                 viewing.setLightPreset(Number(list[0].longitude))
                //                 viewing.setEnvMapBackground(Number(list[0].latitude))
                //                 if (list[0].altitude) viewing.setGroundShadowColor(new THREE.Color(list[0].altitude))
                //                 list[0].center = JSON.parse(list[0].center)
                //                 let data = list[0].center
                //                 const defaultViewer = {
                //                     center: new THREE.Vector3(data[0], data[1], data[2]).clone(),
                //                     fov: data[3],
                //                     isOrtho: data[4],
                //                     pivot: new THREE.Vector3(data[5], data[6], data[7]).clone(),
                //                     position: new THREE.Vector3(data[8], data[9], data[10]).clone(),
                //                     up: new THREE.Vector3(data[11], data[12], data[13]).clone(),
                //                     worldUp: new THREE.Vector3(data[14], data[15], data[16]).clone(),
                //                 }
                //                 viewing.autocam.goToView(defaultViewer)
                //                 setTrue()

                //                 // viewing.addEventListener('selection', e => {
                //                 //     // console.log()
                //                 //     // viewing.getProperties(44,(e)=>{
                //                 //     //     console.log(e)
                //                 //     // })
                //                 //     console.log(viewing.navigation.getPivotPoint())
                //                 //     // focus
                //                 // })
                //                 // isolate 隔离
                //             })
                //             setSceneDetailData(list[0])
                //         } else setSceneDetailData()
                //     },
                // )
            })
        })
    }, [getBimFileOrganizationRelations])

    return (
        <div className="ForgeModel">
            <div className="forgeBox" ref={forgeModel} />
            <div className="formBox">
                <Tabs
                    defaultActiveKey="1"
                    centered
                    items={[
                        {
                            label: '场景数据',
                            key: '1',
                            children: (
                                <ScenesFrom
                                    scene={scene}
                                    initializationEvent={initializationEvent}
                                    ModelUrlList={ModelUrlList}
                                />
                            ),
                        },
                        {
                            label: '明细数据',
                            key: '2',
                            children: (
                                <ModelFrom
                                    scene={scene}
                                    ModelEvent={ModelEvent}
                                    ModelSelect={ModelSelect}
                                    SceneDetailData={SceneDetailData}
                                    Viewing={Viewing}
                                    ModelUrlList={ModelUrlList}
                                />
                            ),
                        },
                    ]}
                />
            </div>
        </div>
    )
}

const ScenesFrom = ({ scene, initializationEvent, ModelUrlList }) => {
    const [Cache] = useLocalStorageState('ClientData')
    const [form] = Form.useForm()
    const [parameter] = useState([
        {
            name: 'uuid',
            label: '编号',
            type: 'hidden',
            hidden: true,
        },
        {
            name: 'tableName',
            label: '场景名称',
            rules: true,
            type: 'input',
        },
        {
            name: 'projectUuid',
            label: '所属项目',
            type: 'select',
            rules: true,
            select: {},
        },
        {
            name: 'sortId',
            label: '排序',
            rules: true,
            type: 'inputNumber',
        },
        {
            name: 'isEnabled',
            label: '启用状态',
            type: 'select',
            toString: true,
            rules: true,
            select: { 0: '禁用', 1: '启用' },
        },
        {
            name: 'remark',
            label: '备注信息',
            type: 'textarea',
        },
    ])
    useEffect(() => {
        parameter.find(v => v.name === 'projectUuid').select = Cache.project
        form.setFieldsValue(scene)
    }, [Cache, form, parameter, scene])

    const { run: putScenes } = useRequest(Http, {
        manual: true,
        onSuccess: () => {
            message.success('场景修改成功!')
            initializationEvent.current.reload()
        },
    })

    return (
        <Form
            className="scenesBase"
            form={form}
            layout="vertical"
            onFinish={data => {
                data = { ...scene, ...data }
                putScenes({ url: `putScenes`, data, path: [data.uuid] })
            }}
        >
            <FormItemModal data={parameter} form={form} ModelUrlList={ModelUrlList} />
            <Button block type="primary" onClick={form.submit}>
                保存
            </Button>
        </Form>
    )
}

const ModelFrom = ({ scene, ModelEvent, ModelSelect, SceneDetailData, Viewing, ModelUrlList }) => {
    console.log(ModelSelect)
    const [form] = Form.useForm()
    const [parameter] = useState([
        {
            name: 'uuid',
            label: '编号',
            type: 'hidden',
            hidden: true,
        },
        {
            name: 'storagePath',
            label: '地址',
            type: 'hidden',
            hidden: true,
        },
        {
            name: 'scenesUuid',
            label: '场景id',
            type: 'hidden',
            hidden: true,
        },
        {
            name: 'tableName',
            label: '名称',
            rules: true,
            type: 'input',
        },
        {
            name: 'constitutesUuid',
            label: '模型',
            rules: true,
            type: 'select',
            select: ModelSelect,
        },
        {
            name: 'longitude',
            label: '灯光效果',
            rules: true,
            judge: 'constitutesUuid',
            type: 'select',
            select: LightPreset,
        },
        {
            name: 'latitude',
            label: '背景效果',
            rules: true,
            judge: 'constitutesUuid',
            type: 'select',
            toString: true,
            select: { 0: '禁用', 1: '启用' },
        },
        {
            name: 'altitude',
            label: '阴影效果',
            judge: 'constitutesUuid',
            type: 'color',
        },
        {
            name: 'center',
            label: '视角',
            judge: 'constitutesUuid',
            rules: true,
            type: 'center',
        },
        {
            name: 'pivotPoint',
            label: '轴心',
            judge: 'constitutesUuid',
            type: 'pivotPoint',
        },
        {
            name: 'sortId',
            label: '排序',
            rules: true,
            type: 'inputNumber',
        },
        {
            name: 'isEnabled',
            label: '启用状态',
            type: 'select',
            toString: true,
            rules: true,
            select: { 0: '禁用', 1: '启用' },
        },
    ])

    // 添加forge明细
    const { run: posScenesDetails } = useRequest(Http, {
        manual: true,
        onSuccess: () => message.success('添加成功'),
    })
    // 修改forge明细
    const { run: putScenesDetails } = useRequest(Http, {
        manual: true,
        onSuccess: () => message.success('修改成功'),
    })

    return (
        <Form
            className="scenesBase"
            form={form}
            layout="vertical"
            initialValues={{ scenesUuid: scene.uuid, ...SceneDetailData }}
            onFinish={data => {
                console.log(data)
                data.category = 'Forge'
                data.center = JSON.stringify(data.center)
                if (data.uuid) putScenesDetails({ url: `putScenesDetails`, data, path: [data.uuid] })
                else posScenesDetails({ url: `posScenesDetails`, data })
            }}
            onValuesChange={({ constitutesUuid, longitude, latitude, altitude }) => {
                if (constitutesUuid) ModelEvent.emit({ url: constitutesUuid })
                if (longitude) ModelEvent.emit({ lng: longitude })
                if (latitude) ModelEvent.emit({ lat: latitude })
                if (altitude) ModelEvent.emit({ alt: altitude })
            }}
        >
            <FormItemModal data={parameter} form={form} Viewing={Viewing} ModelUrlList={ModelUrlList} />
            <Button block type="primary" onClick={form.submit}>
                保存
            </Button>
        </Form>
    )
}

const FormItemModal = ({ data, form, Viewing, ModelUrlList }) => {
    return (
        <>
            {data.map((item, index) => {
                switch (item.type) {
                    case 'hidden':
                        return (
                            <Form.Item
                                key={`scenesBase-FormItem-${index}`}
                                name={item.name}
                                label={item.label}
                                className="Hidden"
                                rules={
                                    item.rulesRule
                                        ? item.rulesRule
                                        : [{ required: item.rules, message: `必须填写${item.label}!` }]
                                }
                            >
                                <Input type="hidden" />
                            </Form.Item>
                        )
                    case 'input':
                        return (
                            <Form.Item
                                key={`scenesBase-FormItem-${index}`}
                                name={item.name}
                                label={item.label}
                                className="fromItem"
                                rules={
                                    item.rulesRule
                                        ? item.rulesRule
                                        : [{ required: item.rules, message: `必须填写${item.label}!` }]
                                }
                            >
                                <Input placeholder={`请输入${item.label}`} allowClear />
                            </Form.Item>
                        )
                    case 'textarea':
                        return (
                            <Form.Item
                                key={`scenesBase-FormItem-${index}`}
                                name={item.name}
                                label={item.label}
                                className="fromItem"
                                rules={
                                    item.rulesRule
                                        ? item.rulesRule
                                        : [{ required: item.rules, message: `必须填写${item.label}!` }]
                                }
                            >
                                <TextArea rows={4} placeholder={`请输入${item.label}`} allowClear />
                            </Form.Item>
                        )
                    case 'inputNumber':
                        return (
                            <Form.Item
                                key={`scenesBase-FormItem-${index}`}
                                name={item.name}
                                label={item.label}
                                className="fromItem"
                                rules={
                                    item.rulesRule
                                        ? item.rulesRule
                                        : [{ required: item.rules, message: `必须填写${item.label}!` }]
                                }
                            >
                                <InputNumber style={{ width: '100%' }} placeholder={`请输入${item.label}`} />
                            </Form.Item>
                        )
                    case 'select':
                        const SelectForm = () => {
                            useEffect(() => {
                                if (
                                    item.toString === true &&
                                    (form.getFieldValue(item.name) || form.getFieldValue(item.name) === 0)
                                ) {
                                    form.setFieldsValue({ [item.name]: form.getFieldValue(item.name).toString() })
                                }
                            }, [])
                            return (
                                <Form.Item
                                    name={item.name}
                                    label={item.label}
                                    className="fromItem"
                                    rules={
                                        item.rulesRule
                                            ? item.rulesRule
                                            : [{ required: item.rules, message: `必须选择${item.label}!` }]
                                    }
                                >
                                    <Select
                                        placeholder={`请选择${item.label}`}
                                        showSearch
                                        allowClear
                                        filterOption={(input, option) =>
                                            option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                        filterSort={(optionA, optionB) =>
                                            optionA.children.toLowerCase().localeCompare(optionB.children.toLowerCase())
                                        }
                                        disabled={item.disabled}
                                        onChange={e => {
                                            if (item.name === 'constitutesUuid')
                                                form.setFieldsValue({
                                                    storagePath: ModelUrlList.find(v => v.uuid === e).url,
                                                })
                                        }}
                                    >
                                        {Object.keys(item.select).map(key => {
                                            return (
                                                <Option key={`scenesBase-FormItem-${index}-Option-${key}`} value={key}>
                                                    {item.select[key]}
                                                </Option>
                                            )
                                        })}
                                    </Select>
                                </Form.Item>
                            )
                        }

                        if (item.judge) {
                            if (!form.getFieldValue(item.judge)) {
                                return false
                            }
                        }

                        return <SelectForm key={`scenesBase-FormItem-${index}`} />
                    case 'color':
                        if (item.judge) {
                            if (!form.getFieldValue(item.judge)) {
                                return false
                            }
                        }
                        return (
                            <Form.Item
                                key={`scenesBase-FormItem-${index}`}
                                name={item.name}
                                label={item.label}
                                className="fromItem"
                                rules={
                                    item.rulesRule
                                        ? item.rulesRule
                                        : [{ required: item.rules, message: `必须填写${item.label}!` }]
                                }
                            >
                                <Input
                                    type="color"
                                    allowClear
                                    onChange={e => form.setFieldsValue({ [item.name]: e.target.value })}
                                />
                            </Form.Item>
                        )
                    case 'center':
                        const CenterForm = () => {
                            const [Center, setCenter] = useState(form.getFieldValue(item.name))
                            useEffect(() => form.setFieldsValue({ [item.name]: Center }), [Center])
                            return (
                                <Form.Item
                                    name={item.name}
                                    label={item.label}
                                    className="fromItem"
                                    rules={
                                        item.rulesRule
                                            ? item.rulesRule
                                            : [{ required: item.rules, message: `必须保存${item.label}!` }]
                                    }
                                >
                                    {Center ? (
                                        <div className="BtnList">
                                            <Button
                                                onClick={() => {
                                                    const defaultViewer = {
                                                        center: new THREE.Vector3(
                                                            Center[0],
                                                            Center[1],
                                                            Center[2],
                                                        ).clone(),
                                                        fov: Center[3],
                                                        isOrtho: Center[4],
                                                        pivot: new THREE.Vector3(
                                                            Center[5],
                                                            Center[6],
                                                            Center[7],
                                                        ).clone(),
                                                        position: new THREE.Vector3(
                                                            Center[8],
                                                            Center[9],
                                                            Center[10],
                                                        ).clone(),
                                                        up: new THREE.Vector3(
                                                            Center[11],
                                                            Center[12],
                                                            Center[13],
                                                        ).clone(),
                                                        worldUp: new THREE.Vector3(
                                                            Center[14],
                                                            Center[15],
                                                            Center[16],
                                                        ).clone(),
                                                    }
                                                    Viewing.autocam.goToView(defaultViewer)
                                                }}
                                                style={{ marginRight: 15 }}
                                            >
                                                归位
                                            </Button>
                                            <Button
                                                danger
                                                onClick={() => {
                                                    let arr = []
                                                    const { center, fov, isOrtho, pivot, position, up, worldUp } =
                                                        Viewing.autocam.getCurrentView()
                                                    // !!! 添加轴心点位置
                                                    arr = [
                                                        center.x,
                                                        center.y,
                                                        center.z,
                                                        fov,
                                                        isOrtho,
                                                        pivot.x,
                                                        pivot.y,
                                                        pivot.z,
                                                        position.x,
                                                        position.y,
                                                        position.z,
                                                        up.x,
                                                        up.y,
                                                        up.z,
                                                        worldUp.x,
                                                        worldUp.y,
                                                        worldUp.z,
                                                    ]
                                                    setCenter(arr)
                                                }}
                                            >
                                                更换
                                            </Button>
                                        </div>
                                    ) : (
                                        <Button
                                            block
                                            onClick={() => {
                                                let arr = []
                                                const { center, fov, isOrtho, pivot, position, up, worldUp } =
                                                    Viewing.autocam.getCurrentView()
                                                arr = [
                                                    center.x,
                                                    center.y,
                                                    center.z,
                                                    fov,
                                                    isOrtho,
                                                    pivot.x,
                                                    pivot.y,
                                                    pivot.z,
                                                    position.x,
                                                    position.y,
                                                    position.z,
                                                    up.x,
                                                    up.y,
                                                    up.z,
                                                    worldUp.x,
                                                    worldUp.y,
                                                    worldUp.z,
                                                ]
                                                setCenter(arr)
                                            }}
                                        >
                                            保存视角
                                        </Button>
                                    )}
                                </Form.Item>
                            )
                        }
                        if (item.judge) {
                            if (!form.getFieldValue(item.judge)) {
                                return false
                            }
                        }
                        return <CenterForm key={`scenesBase-FormItem-${index}`} />

                    case 'pivotPoint':
                        const PivotPointForm = () => {
                            const [Center] = useState(form.getFieldValue('center'))
                            return (
                                <Form.Item
                                    // name={item.name}
                                    label={item.label}
                                    className="fromItem"
                                    rules={
                                        item.rulesRule
                                            ? item.rulesRule
                                            : [{ required: item.rules, message: `必须保存${item.label}!` }]
                                    }
                                >
                                    {Center && (
                                        <Button
                                            block
                                            onClick={() => {
                                                let { x, y, z } = Viewing.navigation.getPivotPoint()
                                                const CenterPivot = Center
                                                CenterPivot[5] = x
                                                CenterPivot[6] = y
                                                CenterPivot[7] = z
                                                form.setFieldsValue({ center: CenterPivot })
                                                message.success('轴心设置成功,请保存!')
                                            }}
                                        >
                                            定位轴心点
                                        </Button>
                                    )}
                                </Form.Item>
                            )
                        }
                        return <PivotPointForm key={`PivotPointForm-Item-${index}`} />

                    default:
                        return (
                            <Form.Item
                                key={`scenesBase-FormItem-${index}`}
                                name={item.name}
                                label={item.label}
                                className="fromItem"
                            >
                                <Input readOnly placeholder="格式暂不支持" allowClear />
                            </Form.Item>
                        )
                }
            })}
        </>
    )
}

// 主窗口
export const ForgeModal = ({ data, Off, initializationEvent }) => {
    const { title, scene } = data
    return (
        <Modal
            className="ModalBox"
            open={true}
            footer={null}
            maskClosable={false}
            onCancel={Off}
            destroyOnClose
            title={title}
            width={1600}
            centered
        >
            <APSModal scene={scene} initializationEvent={initializationEvent} />
        </Modal>
    )
}
